#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LENPKT 8192 // lunghezza del pacchetto
// Destinazione
#define DESTINATION "192.168.0.102" // IP del destinatario
#define PORTD 80 // Porta destinazione
// Sorgente
#define SOURCE "192.168.0.101" // IP sorgente
#define PORTS 5678 // Porta sorgente
// Struttura che useremo per il calcolo del checksum TCP
struct checkpkt_header
{
unsigned long saddr;
unsigned long daddr;
char dummy;
unsigned char protocol;
unsigned short len;
struct tcphdr tcp;
};
// Funzione per il calcolo del checksum dell'header IP
unsigned short ip_checksum( unsigned short * b, int len ) {
unsigned long sum = 0; // long = 32bit
// Sommo il pacchetto IP a 16bit alla volta e se il bit pił significativo e settato (1) lo sommo ai primi 16bit
while( len > 0 ) {
sum += *b++; // Unsigned short = 2 bytes (16bit)
len--;
}
while(sum >> 16)
sum = (sum & 0xFFFF) + (sum >> 16);
return ~sum;
}
// Funzione per il calcolo del checksum dell'header TCP
unsigned short tcp_checksum( unsigned short * buf, int len ) {
int nleft = len;
unsigned short *w = buf;
int sum = 0;
unsigned short answer = 0;
while( nleft > 1 ) {
sum += *w++;
nleft -= 2;
}
if( nleft == 1 ) {
*(unsigned char *) (&answer) = *(u_char *) w;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return (answer);
}
// Funzione per l'invio del pacchetto con il flag SYN settato
int sendpkt( int socket, char *destip, char *sourceip, int dport, int sport ) {
char buffer[LENPKT];
// IP Header
struct iphdr *iph = (struct iphdr *) buffer;
// TCP Header ( packet = IP Header + TCP Header )
struct tcphdr *tcph = (struct tcphdr *) ( iph + 1 );
struct sockaddr_in sin;
struct checkpkt_header *checkpkt;
bzero( buffer, LENPKT );
sin.sin_family = AF_INET;
sin.sin_port = htons( dport ); // Port Destination
sin.sin_addr.s_addr = inet_addr( destip ); // IP Destination
// Riempiamo l'header del pacchetto IP
iph->ihl = 5;
iph->version = 4;
iph->tos = 16;
iph->tot_len = sizeof( struct iphdr ) + sizeof( struct tcphdr );
iph->id = htons(52407);
iph->frag_off = 0;
iph->ttl = 64;
iph->protocol = 6;
iph->check = 0;
iph->saddr = inet_addr( sourceip );
iph->daddr = inet_addr( destip );
// Riempiamo l'header del pacchetto TCP
tcph->source = htons( sport );
tcph->dest = htons( dport );
tcph->seq = htonl(1);
tcph->ack_seq = 0;
tcph->doff = 5;
tcph->syn = 1; // Flag SYN
tcph->ack = 0;
tcph->window = htons(32767);
tcph->check = 0; // In teoria impostando a 0 il checksum del tcp (tcp checksum offload) se ne preoccupa la scheda di rete
tcph->urg_ptr = 0;
// Inseriamo il checksum nell'header IP ora che abbiamo riempito tutto
iph->check = ip_checksum( (unsigned short *) buffer, sizeof( struct iphdr ) + sizeof( struct tcphdr ) );
// Calcoliamo il checksum tcp manualmente...
checkpkt = (struct checkpkt_header *) malloc( sizeof( struct checkpkt_header ) );
memset( checkpkt, 0, sizeof( struct checkpkt_header ) );
checkpkt->saddr = iph->saddr;
checkpkt->daddr = iph->daddr;
checkpkt->protocol = IPPROTO_TCP;
checkpkt->len = htons( sizeof(struct tcphdr) );
checkpkt->tcp = *tcph;
tcph->check = tcp_checksum( (unsigned short *) checkpkt, sizeof( struct checkpkt_header ) );
// Invio del pacchetto!
if( sendto( socket, buffer, iph->tot_len, 0, (struct sockaddr *) &sin, sizeof(sin) ) < 0 )
return 1;
return 0;
}
void setsocket( int sd ) {
int yes;
// Diciamo al kernel che abbiamo gią preparato noi l'header IP del pacchetto
if( setsockopt( sd, IPPROTO_IP, IP_HDRINCL, &yes, sizeof(yes) ) < 0 ) {
fprintf( stderr, "[ERROR] %s", strerror( errno ) );
exit(0);
}
return;
}
int main(){
int sock;
if( geteuid() ){
fprintf( stderr, "[ERROR] Bisogna avere i permessi di root per eseguire l'applicazione\n" );
exit(0);
}
sock = socket( PF_INET, SOCK_RAW, IPPROTO_TCP );
if( sock < 0 ) {
fprintf( stderr, "[ERROR] %s", strerror( errno ) );
exit(0);
}
setsocket( sock );
if( !sendpkt( sock, DESTINATION, SOURCE, PORTD, PORTS ) )
printf( "Pacchetto inviato!\n\n" );
else
printf( "Pacchetto non inviato!\n\n" );
return 0;
}